package cn.coisini.model.common.aspect;

import cn.coisini.model.common.annotation.RedisCache;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @author xiangshaw
 * Description: redis缓存切面
 */
@Aspect
@Component
@RequiredArgsConstructor
public class RedisCacheAspect {

    private final RedisTemplate<Object, Object> redisTemplate;

    @Around("@annotation(redisCache)")
    public Object handleCache(ProceedingJoinPoint joinPoint, RedisCache redisCache) throws Throwable {
        String key = redisCache.key();
        RedisCache.OperationType operation = redisCache.operation();
        boolean refresh = redisCache.refresh();
        long timeout = redisCache.timeout();

        // 处理缓存操作
        switch (operation) {
            case GET:
                // 查询缓存
                if (!refresh && Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
                    return redisTemplate.opsForValue().get(key);
                }
                // 执行业务逻辑
                Object result = joinPoint.proceed();
                // 将结果存入缓存
                if (timeout > 0) {
                    redisTemplate.opsForValue().set(key, result, timeout, TimeUnit.SECONDS);
                } else {
                    redisTemplate.opsForValue().set(key, result);
                }
                return result;
            case SAVE:
            case UPDATE:
                // 执行业务逻辑
                Object updateResult = joinPoint.proceed();
                // 更新缓存
                redisTemplate.opsForValue().set(key, updateResult);
                return updateResult;
            case DELETE:
                // 执行业务逻辑
                Object deleteResult = joinPoint.proceed();
                // 删除缓存
                redisTemplate.delete(key);
                return deleteResult;
            default:
                throw new UnsupportedOperationException("Unsupported Redis operation type.");
        }
    }
}
